//
//  NSObject+NSDictionary.m
//  CCDemo
//
//  Created by 许 强 on 13-7-15.
//  Copyright (c) 2013年 许 强. All rights reserved.
//

#import "NSObject+CCNSDictionary.h"
#include <objc/runtime.h>

static NSString *nullString = @"<null>";

@implementation NSObject (CCNSDictionary)

+ (id)ccObjectFromClassName:(NSString *)className dict:(NSDictionary *)dict {
    Class theClass = NSClassFromString(className);
    return [self ccObjectFromClass:theClass dict:dict];
}



+ (id)ccObjectFromClass:(Class)theClass dict:(NSDictionary *)dict {
    if (NO == [dict isKindOfClass:[NSDictionary class]]) {
        return nil;
    }
    //初始化对象
    id object = [[theClass alloc] init];
    for (NSString *key in [dict allKeys]) {
        id value = [dict objectForKey:key];
        
        NSString * propertyString = [NSString stringWithFormat:@"%@%@",[[key uppercaseString] substringToIndex:1],[key substringFromIndex:1]];
        
        NSString *propertySetSel = [NSString stringWithFormat:@"set%@:",propertyString];
        SEL setterSEL = NSSelectorFromString(propertySetSel);
        SEL getterSEL = NSSelectorFromString(key);
        //当字典的对应value也是字典时触发本方法的循环给属性的属性赋值
        if ([value isKindOfClass:[NSDictionary class]]&&[object respondsToSelector:getterSEL]) {
            
            Class theClass1 = NSClassFromString(key);
            id  tempProp =[[theClass1 alloc]init];
            tempProp =[NSObject ccObjectFromClass:[theClass1 class] dict:value];
                [object performSelector:setterSEL withObject: tempProp] ;
        }
        //当字典的对应value是数组时遍历数组，对value的每一个子字典进行本方法的循环给属性数组内包含的属性赋值
//        else if ([value isKindOfClass:[NSArray class]]&&[object respondsToSelector:getterSEL]){
//            NSMutableArray * arr = [NSMutableArray array];
//            for (id contain in value) {
//                if ([contain isKindOfClass:[NSArray class]]) {
//                     [object performSelector:setterSEL withObject:value];
//                }else if([contain isKindOfClass:[NSDictionary class]]){
//                    Class theClass2 = NSClassFromString(key);
//                    id  tempProp =[[theClass2 alloc]init];
//                    tempProp =[NSObject ccObjectFromClass:[theClass2 class] dict:contain];
//                    NSLog(@"%@",tempProp);
//                    [arr addObject:tempProp];
//                }
//                [object performSelector:setterSEL withObject:arr];
//                }
//        }
        if ([object respondsToSelector:setterSEL]) {
            const char *propertyName = [key cStringUsingEncoding:NSUTF8StringEncoding];
            objc_property_t properties = class_getProperty(theClass, propertyName);
            if (properties) {
                const char *propertyAtt = property_getAttributes(properties);
                NSString *propertyAttS = [NSString stringWithCString:propertyAtt encoding:NSUTF8StringEncoding];
                if ([propertyAttS rangeOfString:@"NSNumber"].length > 0) {
                    if ([value isKindOfClass:[NSString class]]) {
                        NSNumber *newValue = @([value doubleValue]);
                        value = newValue;
                    }
                }
            }
            if ([value isKindOfClass:[NSString class]]) {
                if (![value isEqualToString:nullString]) {
                    [object performSelector:setterSEL withObject:value];
                }
            }
            else if (![value isEqual:[NSNull null]] && ![value isKindOfClass:[NSDictionary class]]) {
                [object performSelector:setterSEL withObject:value];
            }
        }
    }
    return [object autorelease];
}

- (NSDictionary *)ccConvertToDict {
    NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
    
    //获取当前的类
    Class currentClass = [self class];
    NSString *currentClassName = NSStringFromClass(currentClass);
    
    //遍历自身及父类所有property并逐个赋值,直到父类为NSObject停止
    while (NO == [currentClassName isEqualToString:@"NSObject"]) {
        //获取属性
        unsigned int propertyCount;
        
        objc_property_t *properties = class_copyPropertyList(currentClass, &propertyCount);
        for (NSInteger i = 0; i < propertyCount; i++) {
//            objc_property_t property = properties[i];
            const char *property_c = property_getName(properties[i]);
            const char *property_att = property_getAttributes(properties[i]);
            NSString *propertyName = [NSString stringWithUTF8String:property_c];
            NSString *propertyAtt = [NSString stringWithUTF8String:property_att];

            SEL getterSEL = NSSelectorFromString(propertyName);
            id value = nil;
            if ([self respondsToSelector:getterSEL]) {
                value = [self performSelector:getterSEL];
            }
            //防止基本数据类型crash
            //"T@"NSString",&,N,V_userId"
            if (![propertyAtt hasPrefix:@"T@\""]) {
                //是基本数据类型，不处理
                value = nil;
            }
			
            if (value) {
                NSDictionary *dict = @{propertyName:value};
                if ([NSNull null] == value) {
                    continue;
                }
                
                [result addEntriesFromDictionary:dict];
            }
        }
        
        //获取当前的类
        currentClass = [currentClass superclass];
        currentClassName = NSStringFromClass(currentClass);
    }
    
    return [result autorelease];
}


// 不要使用,会导致系统方法被覆盖
//- (id)copyWithZone:(NSZone *)zone {
//    Class currentClass = [self class];
//    
//    unsigned int propertyCount;
//    id objectNew = [[currentClass allocWithZone:zone] init];
//    objc_property_t *properties = class_copyPropertyList(currentClass, &propertyCount);
//    for (NSInteger i = 0; i < propertyCount; i++) {
//        objc_property_t property = properties[i];
//        const char *property_c = property_getName(property);
//        
//        NSString *propertyName = [NSString stringWithUTF8String:property_c];
//        SEL getterSEL = NSSelectorFromString(propertyName);
//        id value = [self performSelector:getterSEL];
//        if (value && propertyName.length > 1) {
//            NSString *setterSELString = [NSString stringWithFormat:@"set%@%@:",[[propertyName substringToIndex:1] uppercaseString],[propertyName substringFromIndex:1]];
//            SEL setterSEL = NSSelectorFromString(setterSELString);
//            id valueNew = [value copy];
//            [objectNew performSelector:setterSEL withObject:valueNew];
//            [valueNew release];
//        }
//    }
//    return objectNew;
//}

@end
